#include "soc_tim_delay.h"

/* 由于时钟不固定,所以定时器的分频系数根据系统时钟定 */
extern uint32_t SystemCoreClock;

void soc_time_delay_init(void)
{
    /* RCC的APB1ENR寄存器的bit4置一,使能 TIM6 时钟 */
    RCC->APB1ENR |= (1<<4);
}

void soc_time_delay_ms(uint16_t ms)
{
    /* 设置定时器预分频系数,TIM6时钟为90MHz,分频后时钟为2KHz即500us,由于PSC为16位寄存器,所以无法分频至1KHz */
    /* 429的时钟频率不固定,为了获取稳定的定时,分频根据系统时钟确定 */
    TIM6->PSC = ((SystemCoreClock / 2 / 2000) - 1);
    //TIM6->PSC = (45000-1);
    /* 重新初始化定时器计数器并生成寄存器更新事件,确保预分频值被采用 */
    TIM6->EGR |= (1 << 0);
    /* 清除更新标志位,该位在发生更新事件时通过硬件置 1,但需要通过软件清零 */
    TIM6->SR = 0;
    /* 设置自动重装载值,定时器计数器的值自增到ARR时,会产生更新事件,ARR的值就是需要延时的时间的一半 */
    TIM6->ARR = (ms * 2);
    /* CR1的bit3(OPM)置一,计数器在发生下一更新事件时停止计数,单脉冲模式 */
    TIM6->CR1 |= (1 << 3);
    /* CR1的bit0(CEN)置一,启动定时器开始计数 */
    TIM6->CR1 |= (1 << 0);
    /* 等待更新事件到来,计数器的值自增到自动重装载寄存器的时候,会产生更新事件,此时延时时间已到 */
    while((TIM6->SR & 0x01)==0);
    /* 清除更新标志位,该位在发生更新事件时通过硬件置 1,但需要通过软件清零 */
    TIM6->SR = 0;

    return;
}

void soc_time_delay_us(uint16_t us)
{
    /* 设置定时器预分频系数,TIM6时钟为90MHz,分频后时钟为1MHz即1us */
    /* 429的时钟频率不固定,为了获取稳定的定时,分频根据系统时钟确定 */
    TIM6->PSC = ((SystemCoreClock / 2 / 1000000) - 1);
    //TIM6->PSC = (90-1);
    /* 重新初始化定时器计数器并生成寄存器更新事件,确保预分频值被采用 */
    TIM6->EGR |= (1 << 0);
    /* 清除更新标志位,该位在发生更新事件时通过硬件置 1,但需要通过软件清零 */
    TIM6->SR = 0;
    /* 设置自动重装载值,定时器计数器的值自增到ARR时,会产生更新事件,ARR的值就是需要延时的时间 */
    TIM6->ARR = us;
    /* CR1的bit3(OPM)置一,计数器在发生下一更新事件时停止计数,单脉冲模式 */
    TIM6->CR1 |= (1 << 3);
    /* CR1的bit0(CEN)置一,启动定时器开始计数 */
    TIM6->CR1 |= (1 << 0);
    /* 等待更新事件到来,计数器的值自增到自动重装载寄存器的时候,会产生更新事件,此时延时时间已到 */
    while ((TIM6->SR & 0x01) == 0);
    /* 清除更新标志位,该位在发生更新事件时通过硬件置 1,但需要通过软件清零 */
    TIM6->SR = 0;

    return;
}
